
#include <MplParserI.h>
#include <Oz/Mpl/UnicodeCharBuffer.hpp>
#include <Oz/Mpl/generated/MplParser.hpp>
#include <Oz/Mpl/generated/MplLexer.hpp>
#include <antlr/TokenBuffer.hpp>
#include <antlr/ANTLRException.hpp>
#include <sstream>
#include <vector>
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>

Oz::Mpl::MplParserI::MplParserI(){

}


Oz::Mpl::MplParserI::~MplParserI(){

}

void Oz::Mpl::MplParserI::setInputFiles(const std::vector<std::string>& inputfiles){
    this->_inputfiles = inputfiles;
}


std::vector<std::string> Oz::Mpl::MplParserI::getInputFiles()const{
    return _inputfiles;
}


void Oz::Mpl::MplParserI::setIncludeDirs(const std::vector<std::string>& includedirs){
    this->_includedirs = includedirs;
}

std::vector<std::string> Oz::Mpl::MplParserI::getIncludeDirs()const{
    return _includedirs;
}

void Oz::Mpl::MplParserI::setDefinitions(const std::vector<std::string>& definitions){
    this->_definitions = definitions;
}

std::vector<std::string> Oz::Mpl::MplParserI::getDefinitions()const{
    return _definitions;
}

void Oz::Mpl::MplParserI::setOutputDir(const std::string& outputdir){
    this->_outputdir = outputdir;
}
std::string Oz::Mpl::MplParserI::getOutputDir()const{
    return _outputdir;
}

std::string Oz::Mpl::MplParserI::parse(const std::string& data){
    ANTLR_USING_NAMESPACE(std)
    ANTLR_USING_NAMESPACE(antlr)
    std::stringstream in;
    in<<data;
    std::cout<<"data: "<<in.str()<<std::endl;
    UnicodeCharBuffer input(in);
    std::cerr<<"UnicodeCharBuffer build OK"<<std::endl;


    MplLexer lexer(input);
    std::cerr<<"MplLexer build OK"<<std::endl;
    lexer.done = false;
    MplParser parser(lexer);
    ASTFactory ast_factory;
    parser.initializeASTFactory(ast_factory);
    parser.setASTFactory(&ast_factory);
    std::cerr<<"MplParser build OK"<<std::endl;
    parser.mpl_class_definition();

    RefAST t = parser.getAST();
    if( t ){
        // Print the resulting tree out in LISP notation
        std::cout<<"tree:"<<std::endl;
        std::cout<<t->toStringTree()<<endl;
    }
    else{
        cout << "No tree produced" << endl;
    }
    return "";
}

int main(int ac,char** av){
    int status = EXIT_SUCCESS;
    try {
        std::string outputdir = "";
        std::string configfile = "";
        // Declare a group of options that will be
        // allowed only on command line
        boost::program_options::options_description generic("Generic options");
        generic.add_options()
            ("version,v", "print version string")
            ("config",boost::program_options::value<std::string>(),"path to config file")
            ("help", "produce help message");

        // Declare a group of options that will be 
        // allowed both on command line and in
        // config file
        boost::program_options::options_description config("Configuration");
        config.add_options()
            ("output-dir", boost::program_options::value<std::string>(&outputdir)->default_value("."),"output directory")
            ("include-path,I",boost::program_options::value<std::vector<std::string> >()->composing(),"include path")
            ("define-var,D",boost::program_options::value<std::vector<std::string> >()->composing(),"define variable");

        // Hidden options, will be allowed both on command line and
        // in config file, but will not be shown to the user.
        boost::program_options::options_description hidden("Hidden options");
        hidden.add_options()
            ("input-file", boost::program_options::value<std::vector<std::string> >(),"input file must use mpl extension");

        boost::program_options::options_description cmdline_options;
        cmdline_options.add(generic).add(config).add(hidden);

        boost::program_options::options_description config_file_options;
        config_file_options.add(config).add(hidden);

        boost::program_options::options_description visible("Allowed options");
        visible.add(generic).add(config);

        boost::program_options::positional_options_description p;
        p.add("input-file",-1);


        boost::program_options::variables_map vm;
        boost::program_options::store(boost::program_options::command_line_parser(ac, av).
              options(cmdline_options).positional(p).run(), vm);

        if (vm.count("config"))
        {
            std::cout << "Config file paths is: " <<vm["config"].as<std::string>() << "\n";
            configfile = vm["config"].as<std::string>();
        }

        if(configfile != ""){
            std::ifstream ifs(configfile.c_str());
            store(parse_config_file(ifs, config_file_options),vm);
            notify(vm);
        }

        if (vm.count("help")) {
            std::cout << visible << "\n";
        }else if (vm.count("version")) {
            std::cout << "MplParser svn-trunk\n";
        }else{
            if(vm.count("output-dir")){
                std::cout << "Output dir: " <<outputdir << "\n";
            }
        }
    }
    catch(const std::exception& std_e)
    {
        std::cerr<<std_e.what()<<std::endl;
        status = EXIT_FAILURE;
    }
    return status;
}
